package ssq.gamest.game;

import com.google.common.base.Objects;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Exceptions;
import org.eclipse.xtext.xbase.lib.Pair;
import ssq.gamest.game.Color;
import ssq.gamest.game.Poker;
import ssq.gamest.game.PokerCard;
import ssq.gamest.game.PokerPattern;

/**
 * 管理单张牌和牌组的大小, 也就是扑克游戏中<b>所有</b>的大小关系
 * 
 * @author s
 */
@SuppressWarnings("all")
public class PokerOrderSettings {
  private final Poker game;
  
  /**
   * 牌组的大小
   */
  public HashMap<Pair<Class<? extends PokerPattern>, Class<? extends PokerPattern>>, Integer> patternOrder = new HashMap<Pair<Class<? extends PokerPattern>, Class<? extends PokerPattern>>, Integer>();
  
  /**
   * id->pattern class
   */
  public Vector<Class<? extends PokerPattern>> idPattern = new Vector<Class<? extends PokerPattern>>();
  
  /**
   * 牌型的拓扑排序
   */
  public Vector<PokerPattern> patternTopologySort = new Vector<PokerPattern>();
  
  public HashMap<Class<? extends PokerPattern>, Double> importance = new HashMap<Class<? extends PokerPattern>, Double>();
  
  /**
   * 比当前id对应的牌型大的牌型id邻接表
   */
  private Vector<LinkedList<Integer>> biggerPatterns = new Vector<LinkedList<Integer>>();
  
  /**
   * 比当前id对应的牌型小的牌型id邻接表
   */
  private Vector<LinkedList<Integer>> smallerPatterns = new Vector<LinkedList<Integer>>();
  
  /**
   * 单张牌的大小
   */
  public List<Integer> pointOrder;
  
  public List<Color> colorOrder;
  
  public boolean withColor = false;
  
  public boolean colorFirst = false;
  
  /**
   * 规则相关
   */
  public List<Color> someColors = new LinkedList<Color>();
  
  public List<Integer> somePoints = new LinkedList<Integer>();
  
  /**
   * 在小端按从小到大的顺序保存两端都允许通过"++"连接的点数
   */
  public List<Integer> twoEndian = new LinkedList<Integer>();
  
  public Vector<Integer> scanListByOrder;
  
  public Vector<Integer> scanListByLiteral = new Vector<Integer>(Collections.<Integer>unmodifiableList(CollectionLiterals.<Integer>newArrayList(Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4), Integer.valueOf(5), Integer.valueOf(6), Integer.valueOf(7), Integer.valueOf(8), Integer.valueOf(9), Integer.valueOf(10), Integer.valueOf(11), Integer.valueOf(12), Integer.valueOf(13), Integer.valueOf(14), Integer.valueOf(15))));
  
  public PokerOrderSettings(final List<Integer> l, final Poker game) {
    this.game = game;
    this.setOrder(l);
  }
  
  public PokerOrderSettings(final List<Integer> li, final List<Color> lc, final boolean colorFirst, final Poker game) {
    this.game = game;
    this.setOrder(li, lc);
    this.colorFirst = colorFirst;
  }
  
  /**
   * 单张牌的大小
   * 
   * @param cards
   */
  public void refreshOrder(final List<PokerCard> cards) {
    for (final PokerCard card : cards) {
      this.refreshOrder(card);
    }
  }
  
  public void refreshOrder(final PokerCard card) {
    int _xifexpression = (int) 0;
    if (this.colorFirst) {
      int _indexOf = this.pointOrder.indexOf(Integer.valueOf(card.point));
      int _indexOf_1 = this.colorOrder.indexOf(card.color);
      int _doubleLessThan = (_indexOf_1 << 4);
      _xifexpression = (_indexOf + _doubleLessThan);
    } else {
      int _indexOf_2 = this.pointOrder.indexOf(Integer.valueOf(card.point));
      int _doubleLessThan_1 = (_indexOf_2 << 3);
      int _xifexpression_1 = (int) 0;
      if (this.withColor) {
        _xifexpression_1 = this.colorOrder.indexOf(card.color);
      } else {
        _xifexpression_1 = 0;
      }
      _xifexpression = (_doubleLessThan_1 + _xifexpression_1);
    }
    card.order = _xifexpression;
  }
  
  /**
   * 返回两种牌型的偏序比较结果. 如果是无法比较, 返回-2
   * 
   * @param p1
   * @param p2
   * @ p1>p2 ? 1 : p1=p2 ? 0 : p1<p2 ? -1 : -2
   */
  public Integer getOrder(final Class<? extends PokerPattern> p1, final Class<? extends PokerPattern> p2) {
    Integer _elvis = null;
    Pair<Class<? extends PokerPattern>, Class<? extends PokerPattern>> _mappedTo = Pair.<Class<? extends PokerPattern>, Class<? extends PokerPattern>>of(p1, p2);
    Integer _get = this.patternOrder.get(_mappedTo);
    if (_get != null) {
      _elvis = _get;
    } else {
      _elvis = Integer.valueOf((-2));
    }
    return _elvis;
  }
  
  /**
   * 会刷新scanListByOrder
   */
  public PokerOrderSettings setPointOrder(final List<Integer> pointOrder) {
    PokerOrderSettings _xblockexpression = null;
    {
      this.pointOrder = pointOrder;
      Vector<Integer> _vector = new Vector<Integer>(pointOrder);
      this.scanListByOrder = _vector;
      boolean _and = false;
      boolean _notEquals = (!Objects.equal(this.twoEndian, null));
      if (!_notEquals) {
        _and = false;
      } else {
        boolean _isEmpty = this.twoEndian.isEmpty();
        boolean _not = (!_isEmpty);
        _and = _not;
      }
      if (_and) {
        this.scanListByOrder.addAll(0, this.twoEndian);
      }
      _xblockexpression = this;
    }
    return _xblockexpression;
  }
  
  public PokerOrderSettings setColorOrder(final List<Color> colorOrder) {
    PokerOrderSettings _xblockexpression = null;
    {
      this.colorOrder = colorOrder;
      _xblockexpression = this;
    }
    return _xblockexpression;
  }
  
  public PokerOrderSettings setSomeColors(final List<Color> someColors) {
    PokerOrderSettings _xblockexpression = null;
    {
      this.someColors = someColors;
      _xblockexpression = this;
    }
    return _xblockexpression;
  }
  
  public PokerOrderSettings setSomePoints(final List<Integer> somePoints) {
    PokerOrderSettings _xblockexpression = null;
    {
      this.somePoints = somePoints;
      _xblockexpression = this;
    }
    return _xblockexpression;
  }
  
  public PokerOrderSettings setTwoEndian(final List<Integer> twoEndian) {
    PokerOrderSettings _xblockexpression = null;
    {
      this.twoEndian = twoEndian;
      this.setPointOrder(this.pointOrder);
      _xblockexpression = this;
    }
    return _xblockexpression;
  }
  
  /**
   * 当花色不影响大小时调用
   */
  public PokerOrderSettings setOrder(final List<Integer> l) {
    PokerOrderSettings _xblockexpression = null;
    {
      this.withColor = false;
      this.setPointOrder(l);
      _xblockexpression = this;
    }
    return _xblockexpression;
  }
  
  /**
   * 当花色也影响大小时调用
   */
  public PokerOrderSettings setOrder(final List<Integer> li, final List<Color> lc) {
    PokerOrderSettings _xblockexpression = null;
    {
      this.withColor = true;
      this.setPointOrder(li);
      this.colorOrder = lc;
      _xblockexpression = this;
    }
    return _xblockexpression;
  }
  
  /**
   * 给牌型的偏序矩阵, 邻接表, 逆邻接表, 拓扑排序表初始化
   */
  public PokerOrderSettings setPatternAndOrder(final List<List<String>> paths) {
    try {
      PokerOrderSettings _xblockexpression = null;
      {
        int _size = paths.size();
        Vector<Vector<Class<? extends PokerPattern>>> pathsVector = new Vector<Vector<Class<? extends PokerPattern>>>(_size);
        for (final List<String> list : paths) {
          {
            Vector<Class<? extends PokerPattern>> tmp = new Vector<Class<? extends PokerPattern>>();
            pathsVector.add(tmp);
            for (final String string : list) {
              try {
                boolean _equals = string.equals("`others`");
                if (_equals) {
                  tmp.add(PokerPattern.class);
                } else {
                  Class<?> _forName = Class.forName(((("ssq.gamest.game." + this.game.packageName) + ".patterns.") + string));
                  Class<? extends PokerPattern> clazz = ((Class<? extends PokerPattern>) _forName);
                  tmp.add(clazz);
                  boolean _contains = this.idPattern.contains(clazz);
                  boolean _not = (!_contains);
                  if (_not) {
                    this.idPattern.add(clazz);
                    LinkedList<Integer> _linkedList = new LinkedList<Integer>();
                    this.smallerPatterns.add(_linkedList);
                    LinkedList<Integer> _linkedList_1 = new LinkedList<Integer>();
                    this.biggerPatterns.add(_linkedList_1);
                    Pair<Class<? extends PokerPattern>, Class<? extends PokerPattern>> _mappedTo = Pair.<Class<? extends PokerPattern>, Class<? extends PokerPattern>>of(clazz, clazz);
                    this.patternOrder.put(_mappedTo, Integer.valueOf(0));
                  }
                }
              } catch (final Throwable _t) {
                if (_t instanceof ClassNotFoundException) {
                  final ClassNotFoundException e = (ClassNotFoundException)_t;
                  e.printStackTrace();
                  System.exit((-1));
                } else {
                  throw Exceptions.sneakyThrow(_t);
                }
              }
            }
          }
        }
        for (Iterator<Vector<Class<? extends PokerPattern>>> iterator = pathsVector.iterator(); iterator.hasNext();) {
          {
            Vector<Class<? extends PokerPattern>> vector = iterator.next();
            for (int i = (vector.size() - 1); (i >= 0); i--) {
              {
                Class<? extends PokerPattern> bigger = vector.get(i);
                for (int j = (i - 1); (j >= 0); j--) {
                  {
                    Class<? extends PokerPattern> smaller = vector.get(j);
                    boolean _equals = Objects.equal(smaller, PokerPattern.class);
                    if (_equals) {
                      for (int k = 0; (k < this.idPattern.size()); k++) {
                        {
                          Class<? extends PokerPattern> mayBeSmaller = this.idPattern.get(k);
                          Pair<Class<? extends PokerPattern>, Class<? extends PokerPattern>> _mappedTo = Pair.<Class<? extends PokerPattern>, Class<? extends PokerPattern>>of(bigger, mayBeSmaller);
                          boolean _containsKey = this.patternOrder.containsKey(_mappedTo);
                          boolean _not = (!_containsKey);
                          if (_not) {
                            this.add(bigger, mayBeSmaller);
                          }
                        }
                      }
                    } else {
                      this.add(bigger, smaller);
                    }
                  }
                }
              }
            }
          }
        }
        int _size_1 = this.biggerPatterns.size();
        Vector<LinkedList<Integer>> copyOfBiggerPatterns = new Vector<LinkedList<Integer>>(_size_1);
        for (int i = 0; (i < this.biggerPatterns.size()); i++) {
          {
            LinkedList<Integer> _get = this.biggerPatterns.get(i);
            Object _clone = _get.clone();
            LinkedList<Integer> tmp = ((LinkedList<Integer>) _clone);
            copyOfBiggerPatterns.add(tmp);
          }
        }
        while ((!this.isEmpty(copyOfBiggerPatterns))) {
          {
            Set<Class<? extends PokerPattern>> _keySet = this.importance.keySet();
            for (final Class<? extends PokerPattern> pattern : _keySet) {
              Double _get = this.importance.get(pattern);
              double _multiply = ((_get).doubleValue() * 16);
              this.importance.put(pattern, Double.valueOf(_multiply));
            }
            LinkedList<Class<? extends PokerPattern>> toBeCleared = new LinkedList<Class<? extends PokerPattern>>();
            LinkedList<Class<? extends PokerPattern>> mayBeCleared = new LinkedList<Class<? extends PokerPattern>>();
            int maxDepth = (-1);
            for (int i = 0; (i < copyOfBiggerPatterns.size()); i++) {
              {
                LinkedList<Integer> item = copyOfBiggerPatterns.get(i);
                boolean _and = false;
                boolean _notEquals = (!Objects.equal(item, null));
                if (!_notEquals) {
                  _and = false;
                } else {
                  int _size_2 = item.size();
                  boolean _equals = (_size_2 == 0);
                  _and = _equals;
                }
                if (_and) {
                  final Class<? extends PokerPattern> pattern_1 = this.idPattern.get(i);
                  mayBeCleared.add(pattern_1);
                  LinkedList<Integer> _get_1 = this.smallerPatterns.get(i);
                  int _size_3 = _get_1.size();
                  int _max = Math.max(_size_3, maxDepth);
                  maxDepth = _max;
                }
              }
            }
            LinkedList<PokerPattern> toBeAdded = new LinkedList<PokerPattern>();
            for (final Class<? extends PokerPattern> pattern_1 : mayBeCleared) {
              int _indexOf = this.idPattern.indexOf(pattern_1);
              LinkedList<Integer> _get_1 = this.smallerPatterns.get(_indexOf);
              int _size_2 = _get_1.size();
              boolean _equals = (_size_2 == maxDepth);
              if (_equals) {
                toBeCleared.add(pattern_1);
                PokerPattern _newInstance = pattern_1.newInstance();
                toBeAdded.add(_newInstance);
                this.importance.put(pattern_1, Double.valueOf(8.0));
              }
            }
            try {
              Collections.<PokerPattern>sort(toBeAdded, new Comparator() {
                @Override
                public int compare(final Object arg0, final Object arg1) {
                  try {
                    Class<?> _class = arg1.getClass();
                    Field _declaredField = _class.getDeclaredField("leastCards");
                    int _int = _declaredField.getInt(null);
                    Class<?> _class_1 = arg0.getClass();
                    Field _declaredField_1 = _class_1.getDeclaredField("leastCards");
                    int _int_1 = _declaredField_1.getInt(null);
                    return (_int - _int_1);
                  } catch (Throwable _e) {
                    throw Exceptions.sneakyThrow(_e);
                  }
                }
              });
            } catch (final Throwable _t) {
              if (_t instanceof Exception) {
                final Exception e = (Exception)_t;
                e.printStackTrace();
              } else {
                throw Exceptions.sneakyThrow(_t);
              }
            }
            this.patternTopologySort.addAll(toBeAdded);
            boolean _and = false;
            int _size_3 = toBeCleared.size();
            boolean _equals_1 = (_size_3 == 0);
            if (!_equals_1) {
              _and = false;
            } else {
              boolean _isEmpty = this.isEmpty(copyOfBiggerPatterns);
              boolean _not = (!_isEmpty);
              _and = _not;
            }
            if (_and) {
              throw new Exception("**********出现循环包含");
            }
            for (final Class<? extends PokerPattern> item_ : toBeCleared) {
              {
                int _indexOf_1 = this.idPattern.indexOf(item_);
                copyOfBiggerPatterns.set(_indexOf_1, null);
                for (final LinkedList<Integer> item : copyOfBiggerPatterns) {
                  boolean _notEquals = (!Objects.equal(item, null));
                  if (_notEquals) {
                    int _indexOf_2 = this.idPattern.indexOf(item_);
                    Integer _valueOf = Integer.valueOf(_indexOf_2);
                    item.remove(_valueOf);
                  }
                }
              }
            }
          }
        }
        _xblockexpression = this;
      }
      return _xblockexpression;
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  public boolean isEmpty(final Vector<LinkedList<Integer>> list2) {
    boolean _xblockexpression = false;
    {
      for (final List list : list2) {
        boolean _notEquals = (!Objects.equal(list, null));
        if (_notEquals) {
          return false;
        }
      }
      _xblockexpression = true;
    }
    return _xblockexpression;
  }
  
  public void add(final Class<? extends PokerPattern> bigger, final Class<? extends PokerPattern> smaller) {
    int biggerIndex = this.idPattern.indexOf(bigger);
    int smallerIndex = this.idPattern.indexOf(smaller);
    Pair<Class<? extends PokerPattern>, Class<? extends PokerPattern>> _mappedTo = Pair.<Class<? extends PokerPattern>, Class<? extends PokerPattern>>of(bigger, smaller);
    this.patternOrder.put(_mappedTo, Integer.valueOf(1));
    Pair<Class<? extends PokerPattern>, Class<? extends PokerPattern>> _mappedTo_1 = Pair.<Class<? extends PokerPattern>, Class<? extends PokerPattern>>of(smaller, bigger);
    this.patternOrder.put(_mappedTo_1, Integer.valueOf((-1)));
    LinkedList<Integer> _get = this.smallerPatterns.get(biggerIndex);
    _get.add(Integer.valueOf(smallerIndex));
    LinkedList<Integer> _get_1 = this.biggerPatterns.get(smallerIndex);
    _get_1.add(Integer.valueOf(biggerIndex));
  }
  
  public Vector<Integer> getScanList(final boolean byOrder) {
    Vector<Integer> _xifexpression = null;
    if (byOrder) {
      _xifexpression = this.scanListByOrder;
    } else {
      _xifexpression = this.scanListByLiteral;
    }
    return _xifexpression;
  }
}
